#pragma once
#ifndef __G_MATRIX_3X3_H__
#define __G_MATRIX_3X3_H__

#include "GVector2.h"
#include "GVector3.h"
#include "GUtilities/GTypes.h"

/* Disable Anonymous Unions Warning */
#pragma warning(disable:4201)

namespace GMath
{

	class GMatrix3x3
	{
	public:
		const static GMatrix3x3	Zero;
		const static GMatrix3x3	One;
		const static GMatrix3x3	Identity;

		union 
		{
			struct
			{
				float		I11, I12, I13;
				float		I21, I22, I23;
				float		I31, I32, I33;
			};

			float			Mat[3][3];
			float			Arr[9];
		};

							GMatrix3x3();
							GMatrix3x3(	float M11, float M12, float M13,
										float M21, float M22, float M23,
										float M31, float M32, float M33);

							operator float* ();
							operator const float* () const;

		float				Determinant() const;

		bool				Inverse();
		static bool			Inverse(OUTPUT GMatrix3x3& OutMatrix, const GMatrix3x3& Matrix);

		void				Transpose();
		static void			Transpose(OUTPUT GMatrix3x3& OutMatrix, const GMatrix3x3& Matrix);

		static void			Decompose(OUTPUT GVector2& OutScale, OUTPUT float& OutRotation, OUTPUT GVector2& OutTranslation, const GMatrix3x3& Matrix);

		static void			Multiply(OUTPUT GVector2& Output, const GVector2& Vector, const GMatrix3x3& Matrix);
		static void			Multiply(OUTPUT GVector3& Output, const GVector3& Vector, const GMatrix3x3& Matrix);
		static void			Multiply(OUTPUT GMatrix3x3& Output, const GMatrix3x3& MatrixA, const GMatrix3x3& MatrixB);

		float				operator () (GUInt32 Row, GUInt32 Column);
		float				operator () (GUInt32 Row, GUInt32 Column) const;

		GMatrix3x3&			operator  =	(const GMatrix3x3& Matrix);
		GMatrix3x3&			operator += (const GMatrix3x3& Matrix);
		GMatrix3x3&			operator -= (const GMatrix3x3& Matrix);
		GMatrix3x3&			operator *= (const GMatrix3x3& Matrix);
		GMatrix3x3&			operator *= (const float);
		GMatrix3x3&			operator /= (const float);

		GMatrix3x3			operator + (const GMatrix3x3& Matrix) const;
		GMatrix3x3			operator - (const GMatrix3x3& Matrix) const;
		GMatrix3x3			operator * (const GMatrix3x3& Matrix) const;
		GMatrix3x3			operator * (const float Value) const;
		GMatrix3x3			operator / (const float Value) const;

		GMatrix3x3			operator + () const;
		GMatrix3x3			operator - () const;

		bool				operator == (const GMatrix3x3& Matrix) const;
		bool				operator != (const GMatrix3x3& Matrix) const;

		friend GMatrix3x3	operator * (float Value, const GMatrix3x3& Matrix);
		friend GVector3		operator * (const GVector3& Vector, const GMatrix3x3& Matrix);
		friend GVector2		operator * (const GVector2& Vector, const GMatrix3x3& Matrix);
	
	};

}

#endif
